#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <QFile>
#include <fcntl.h>
#include "xmovieplayer.h"
#include <xwritelogexport.h>
#include <qtimer.h>
#include "infomatcommon.h"

/* *********************************************************************
 *     PUBLIC FUNCTION
 * *********************************************************************/
XMoviePlayer::XMoviePlayer(QObject* parent) :QObject(parent),
	 m_fdIn(-1), m_fdOut(-1), m_timeout(0),m_isIdle(true), m_hasSentStop(false)
{
	m_fdIn = open(k_fifo_cplayer_in,O_WRONLY, O_NONBLOCK);
	if (-1==m_fdIn) {
		LOG_E("Error:%s with errno:%d, EXIT", strerror(errno), m_fdIn);
	}
	m_xFifoRead = new XFifoReadThread(this);
	assert (NULL!=m_xFifoRead);
	m_xFifoRead->start();
	connect (m_xFifoRead, SIGNAL(sgStopEnd()), this, SLOT(onStopEnd()));
	/* --Not Start Players Yet ---*/
}

XMoviePlayer::~XMoviePlayer()
{
	close(m_fdIn);
//	LOG_E("Delete m_xFifoRead");
	if (NULL!=m_xFifoRead) {
		delete m_xFifoRead;
		m_xFifoRead = NULL;;
	}
}

void XMoviePlayer::stopPlay()
{
//	LOG_E("m_isIdle = %02d (0-False 1-True)", m_isIdle);
	if (m_isIdle) {
		LOG_E("[CPLAYER] [IDLE] [Already]");
		emit sgCPlayerIdle();
	} else {
		if (false == m_hasSentStop) {  // Send Once Only
			LOG_E("CPlayer.Busy.Send.S");
//			clearPicutreConnection();   // Note: Cannot Clear Connection here
//			clearVideoConnection();     // ~~~
			sendCmdToFIFO(EStop, "");
			m_hasSentStop = true;
		} else {
			LOG_E("[IGNORE] Require Sent S Again");
		}
	}
}

void XMoviePlayer::playMovie(const char* file, const int timeout, const int picIndex)
{   /* PLAY PICTURE */
	m_picIndex = picIndex;   
	m_timeout = timeout;
	clearPicutreConnection();
	clearVideoConnection();
	connect(m_xFifoRead,SIGNAL(sgPlayEnd()), this, SLOT(onFinishPicture()));
	assert (NULL!=file);
	QString arguments = QString(file);
//	LOG_E("Play Picture: m_isIdle = False");
	m_isIdle = false;
	m_hasSentStop = false;
	sendCmdToFIFO(EOpen, arguments.toStdString().c_str());
}

void XMoviePlayer::playMovie(const char* file, const int videoIndex)
{   /*  PLAY VIDEO */ /* Manager knows cplayer STOP */
//	LOG_E("=== Playing Video =====");
	assert (NULL!=file);
	m_videoIndex = videoIndex;
	QString arguments =	 QString(file);
	clearPicutreConnection();
	clearVideoConnection();
	connect(m_xFifoRead, SIGNAL(sgPlayEnd()), this, SLOT(onPlayVideoDone()));
	m_isIdle = false;
	m_hasSentStop = false;
//	LOG_E("arugment:[%s]", arguments.toStdString().c_str());
	sendCmdToFIFO(EOpen, arguments.toStdString().c_str());
}

void XMoviePlayer::clearVideoConnection()
{
	disconnect (m_xFifoRead, SIGNAL(sgPlayEnd()), this, SLOT(onPlayVideoDone()));
}

void XMoviePlayer::clearPicutreConnection()
{
	m_tmPicture.stop();
	disconnect (&m_tmPicture, SIGNAL(timeout()), this, SLOT(onPlayPictureDone()));
	disconnect(m_xFifoRead, SIGNAL(sgPlayEnd()), this, SLOT(onFinishPicture()));
}

void XMoviePlayer::setPlayerGeometry(const int x, const int y, const int width, const int heigh)   // [+]
{
	QString arguments = QString::number(x) + QString(",") +
		                QString::number(y) + QString(",") +
						QString::number(width) + QString(",") +
						QString::number(heigh);
	if (m_isIdle) { 
//		LOG_E("[OK] Set Geometry: CPlayer State: Stop");
		sendCmdToFIFO(EGeometry, arguments.toStdString().c_str());
	} else {
		LOG_E("[Fail]Set Geometry, CPlayer State: Running");
	}
	return;
}

/* ****************************************************************************
 *  					PROTECTED
 * ***************************************************************************/
void XMoviePlayer::sendCmdToFIFO(const int in_cmdType, const char* in_cmdMsg)
{
	assert (m_fdIn != -1);
	assert (NULL!=in_cmdMsg);

	QString arguments;
	switch (in_cmdType)
	{
	case EStop:
		arguments = "s" + QString("\n");
		break;
	case EOpen:
		arguments = "o " + QString(in_cmdMsg) + QString("\n");;
		break;
	case EGeometry:
		arguments = "L " + QString(in_cmdMsg) + QString("\n");
		break;
	default:
		LOG_E("Send wrong command type");
	}
	int length = write(m_fdIn, arguments.toStdString().c_str(), arguments.size());
	if (-1==length) {
		LOG_E("error:%s with errno: %d, EXIT",strerror(errno),length);
	} else {
		LOG_E("command to fifo:[%s]", arguments.toStdString().c_str());
	}
}

/* ==================================================================
 * ==========SIGNAL - SLOT ==========================================
 * ==================================================================*/
void XMoviePlayer::onPlayPictureDone()
{
	LOG_E("=========================================");
	LOG_E(" [Finish] PICTURE TIMER  m_picIndex:%02d ",m_picIndex);
	LOG_E("=========================================");
	m_isIdle = true;
	m_hasSentStop = false;
	m_tmPicture.stop();
	disconnect(&m_tmPicture, SIGNAL(timeout()), this, SLOT(onPlayPictureDone()));
	emit sgPlayMovieDone(m_picIndex);
}
void XMoviePlayer::onPlayVideoDone()
{
	LOG_E("========================================");
	LOG_E(" [Finish] VIDEO SIGNAL :m_videoIndex=%02d", m_videoIndex);
	LOG_E("========================================");
	m_isIdle=true;
	m_hasSentStop = false;
	disconnect(m_xFifoRead, SIGNAL(sgPlayEnd()), this, SLOT(onPlayVideoDone()));
//	LOG_E("[EMIT TO] [LayoutManager] sgPlayMovieDone");
	emit sgPlayMovieDone(m_videoIndex);     // notify xinfomatLayoutManager
}

void XMoviePlayer::onFinishPicture()
{
//	LOG_E("Finish.Display.Picutre");
	m_isIdle = true;
	disconnect(m_xFifoRead, SIGNAL(sgPlayEnd()), this, SLOT(onFinishPicture()));
	connect(&m_tmPicture, SIGNAL(timeout()), this, SLOT(onPlayPictureDone()));
	m_tmPicture.start(m_timeout);
}

void XMoviePlayer::onStopEnd()
{
//	LOG_E("========================");
	LOG_E("[CPLAYER][STOP][SUCCESS]");
//	disconnect (m_xFifoRead, SIGNAL(sgStopEnd()), this, SLOT(onStopEnd()));  //Avoid Queue
	m_isIdle = true;
//	LOG_E("==========================");
	LOG_E("\n\n");
	m_hasSentStop = false;
	emit sgCPlayerIdle();
}
